package com.hs.srm.admin.modules.invoice.controller;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.hs.srm.admin.modules.bills.entity.ScmBillsEntity;
import com.hs.srm.admin.modules.bills.entity.ScmBillsHeaderEntity;
import com.hs.srm.admin.modules.bills.service.ScmBillsHeaderService;
import com.hs.srm.admin.modules.bills.service.ScmBillsService;
import com.hs.srm.admin.modules.invoice.entity.ScmInvoiceEntity;
import com.hs.srm.admin.modules.invoice.entity.ScmInvoiceHeaderEntity;
import com.hs.srm.admin.modules.invoice.service.InvoiceHeaderService;
import com.hs.srm.admin.modules.invoice.service.InvoiceService;
import com.hs.srm.admin.modules.orders.service.StockService;
import com.hs.srm.admin.modules.sys.controller.AbstractController;
import com.hs.srm.admin.modules.vendor.entity.VendorInfoEntity;
import com.hs.srm.admin.modules.vendor.service.VendorService;
import com.hs.srm.base.common.annotation.SysLog;
import com.hs.srm.base.common.utils.DictDataUtil;
import com.hs.srm.base.common.utils.DictDataUtil.DictType;
import com.hs.srm.base.common.utils.EntityUtils;
import com.hs.srm.base.modules.sys.entity.SysUserEntity;
import com.hs.srm.common.utils.PageUtils;
import com.hs.srm.common.utils.R;
import com.sap.conn.jco.*;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import sunnykid.character.UtilCharacter;
import sunnykid.lang.LangException;
import sunnykid.lang.SunnykidDate;
import sunnykid.lang.SunnykidNumber;
import sunnykid.util.ArrayUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

import static com.hs.srm.admin.modules.bills.entity.ScmBillsHeaderEntity.InvoiceStatus;
import static com.hs.srm.admin.modules.invoice.entity.ScmInvoiceHeaderEntity.DealStatus;

/**
 * <p>標題：发票数据controller层</p>
 * <p>描述：</p>
 * <p>版權：版權所有 (c) 2019</p>
 * <p>組織：厚声集团</p>
 *
 * @author 鐘曉籟
 * @version V1.0.0
 * @date 2019年4月2日 上午9:49:54
 * @since V1.0.0
 */
@RestController
@RequestMapping("/invoice")
public class InvoiceController extends AbstractController {

    /**
     * 类序列ID
     */
    private static final long serialVersionUID = -2392337998173025326L;

    @Autowired
    private InvoiceService invoiceService;

    @Autowired
    private InvoiceHeaderService invoiceHeaderService;

    @Autowired
    private ScmBillsService scmBillsService;

    @Autowired
    private ScmBillsHeaderService scmBillsHeaderService;

    @Autowired
    private StockService stockService;

    @Autowired
    private VendorService vendorService;

    /**
     * 转向到预制发票的页面
     */
    @RequestMapping("/toGenInvoice")
    public ModelAndView toGenInvoice(String billHeadId) {
        ScmBillsHeaderEntity she = this.scmBillsHeaderService.selectById(billHeadId);
        EntityWrapper<VendorInfoEntity> queryWrapper = new EntityWrapper<>();
        queryWrapper.eq("sap_code", she.getVendorId());
        VendorInfoEntity vendor = this.vendorService.selectOne(queryWrapper);
        ScmInvoiceHeaderEntity invoiceHeader = new ScmInvoiceHeaderEntity();
        invoiceHeader.setSumMoney(she.getSumMoney());
        invoiceHeader.setVendorCode(vendor.getSapCode());
        invoiceHeader.setVendorId(vendor.getPkId());
        invoiceHeader.setVendorName(vendor.getVendorName());
        invoiceHeader.setBillNo(she.getBillNo());
        invoiceHeader.setCurrency(vendor.getOrderCurrency());
        invoiceHeader.setCurrencyText(DictDataUtil.valToTxt(vendor.getOrderCurrency(), DictType.BZ));
        invoiceHeader.setTaxCode(vendor.getTaxCode());
        invoiceHeader.setTaxCodeText(DictDataUtil.valToTxt(vendor.getTaxCode(), DictType.SDM));
        invoiceHeader.setPayCondition(vendor.getPayCondition());
        invoiceHeader.setPayConditionText(DictDataUtil.valToTxt(vendor.getPayCondition(), DictType.FKTJ));
        invoiceHeader.setDateGz(new Date());
        ModelAndView modelAndView = new ModelAndView("modules/invoice/invoice_deal.html");
        modelAndView.addObject("invoiceHeader", invoiceHeader);
        return modelAndView;
    }

    /**
     * 生成预制发票
     */
    @RequestMapping(value = "/genInvoices", produces = {"application/json"}, consumes = {"application/x-www-form-urlencoded"})
    // @RequiresPermissions("vendorEnclosure:save")
    public R genInvoices(ScmInvoiceHeaderEntity formData) {
        if (formData != null) {
            formData.setCreationDate(new Date());
            formData.setCreatedBy(this.getUser().getName());
            this.invoiceHeaderService.insert(formData);
            ScmBillsHeaderEntity bill = this.scmBillsHeaderService.selectList(
                    new EntityWrapper<ScmBillsHeaderEntity>().eq("bill_no", formData.getBillNo())).get(0);
            bill.setInvoiceStatus(ScmBillsHeaderEntity.InvoiceStatus.YIKAIPAI_WEISHENPI);
            this.scmBillsHeaderService.updateById(bill);
            return R.ok();
        }
        return R.error();
    }

    /**
     * 审核预制发票
     */
    @SysLog("审核预制发票")
    @RequestMapping("/checkInvoice")
    public R checkInvoice(String pkId, boolean agree) {
        ScmInvoiceHeaderEntity inv = this.invoiceHeaderService.selectById(pkId);
        int status = inv.getDealStatus().intValue();
        if ((status > 0 && agree) || (status < 0 && !agree)) {
            return R.error("已经审核过了");
        }
        String msg = null;
        //审核通过才能同步SAP
        if (agree) {
            msg = this.sendInvoiceToSap(inv);
        }
        inv.setDealStatus(agree ? DealStatus.YUZHI_PASS : DealStatus.YUZHI_FAIL);
        this.invoiceHeaderService.updateById(inv);
        ScmBillsHeaderEntity scmBillsHeader = this.scmBillsHeaderService
                .selectOne(new EntityWrapper<ScmBillsHeaderEntity>().eq("bill_no", inv.getBillNo()));
        if (scmBillsHeader != null) {
            // 2开票审批通过；-2开票审批未通过
            scmBillsHeader.setInvoiceStatus(agree ? InvoiceStatus.SHENPI_TONGGUO : InvoiceStatus.SHENPI_BOHUI);
        }
        return R.ok(msg);
    }

    /**
     * @Description SAP发票创建接口
     * @Param [pkIds, agree]
     * @Return com.hs.srm.common.utils.R
     * @Author socik
     * @Date 2019/5/10 14:05
     * <p>
     */
    public String sendInvoiceToSap(ScmInvoiceHeaderEntity scmInvoiceHeaderEntity) {
        logger.debug("发票创建接口!");
        JCoDestination destination = null;
        JCoFunction function = null;
        JCoParameterList tables = null;
        JCoParameterList importList = null;
        JCoParameterList returnList = null;
        // 根据对账单id找到对账单信息
        List<ScmBillsEntity> billsEntity = this.scmBillsService.selectListByBillNo(scmInvoiceHeaderEntity.getBillNo());
        // 调用SAP接口
        try {
            destination = JCoDestinationManager.getDestination("IDOC_AFS");
            function = destination.getRepository().getFunction("ZFM_SRM_INCOMINGINVOICE_PARK");
            tables = function.getTableParameterList();
            importList = function.getImportParameterList();
            returnList = function.getExportParameterList();
        } catch (JCoException e) {
            e.printStackTrace();
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        // 传入 发票抬头
        JCoStructure value_desc = importList.getStructure("IS_HEAD");
        // 获取收货年度
        String year = String.format("%tY", scmInvoiceHeaderEntity.getDateGz());
        // 提取当前月的第一天和最后一天
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat datef = new SimpleDateFormat("yyyyMMdd");
        // 当前月的最后一天
        cal.set(Calendar.DATE, 1);
        cal.roll(Calendar.DATE, -1);
        Date endTime = cal.getTime();
        String endTime1 = datef.format(endTime);
        // 当前月的第一天
        cal.set(GregorianCalendar.DAY_OF_MONTH, 1);
        Date beginTime = cal.getTime();
        String beginTime1 = datef.format(beginTime);
        // 公司代码
        value_desc.setValue("BUKRS", billsEntity.get(0).getCompanyCode());
        // 抬头文本
        value_desc.setValue("BKTXT", scmInvoiceHeaderEntity.getBkTxt());
        // 凭证日期
        value_desc.setValue("BLDAT", simpleDateFormat.format(scmInvoiceHeaderEntity.getDateKp()));
        // 过账日期
        value_desc.setValue("BUDAT", endTime1);
        // 货币类型
        value_desc.setValue("WAERS", scmInvoiceHeaderEntity.getCurrency());
        // 供应商发票
        value_desc.setValue("REF_DOC_NO", scmInvoiceHeaderEntity.getInvoiceNo());
        // 传入发票行项目 采购订单号 行项目 收获订单号 收获行项目
        JCoTable jCoFieldsTable = tables.getTable("IT_ITEM");
        billsEntity.forEach(scmBillsEntity -> {
            String taxTxt = DictDataUtil.valToTxt(scmBillsEntity.getTaxCode(), DictType.SDM);
            Double texTax = Double.valueOf(InvoiceController.getNumFromStr(taxTxt.substring(
                    taxTxt.indexOf("-") + "-".length(), taxTxt.indexOf("%"))));
            // 根据订单号和行项目查询收获表 获取收货年度 收货凭证号 收货凭证行项目
            var stockEntity = this.stockService.selectStockByPo(scmBillsEntity.getPoNo(),
                    scmBillsEntity.getItemNo());

            jCoFieldsTable.appendRow();
            // 采购订单号
            jCoFieldsTable.setValue("EBELN", scmBillsEntity.getPoNo());
            // 采购订单行项目
            jCoFieldsTable.setValue("EBELP", scmBillsEntity.getItemNo());
            // 收获凭证号
            jCoFieldsTable.setValue("LFBNR", stockEntity.getMblnr());
            // 收获年度
            jCoFieldsTable.setValue("LFGJA", year);
            // 收获凭证行项目
            jCoFieldsTable.setValue("LFPOS", stockEntity.getZeile());
            // 税码
            jCoFieldsTable.setValue("MWSKZ", scmBillsEntity.getTaxCode());
            // 数量
            jCoFieldsTable.setValue("MENGE", scmBillsEntity.getPoCount() + "");
            // 金额
            jCoFieldsTable.setValue(
                    "DMBTR",
                    new SunnykidNumber((scmBillsEntity.getPoPrice().multiply(scmBillsEntity.getPoCount()))
                            .doubleValue() / ((1 + (texTax / 100))) + "").parseSizedNumber(2));
            // 单位
            jCoFieldsTable.setValue("MEINS", scmBillsEntity.getPoUnit());
        });
        try {
            function.execute(destination);
        } catch (JCoException e) {
            logger.error("创建发票号失败!", e);
            throw new RuntimeException("SAP调用异常");
        }
        JCoTable returnTable = tables.getTable("ET_MSEG");
        String invdocno = returnList.getString("E_INVNUM");
        if (invdocno != null && invdocno != "") {
            scmInvoiceHeaderEntity.setKjpzbh(invdocno);
            boolean flg = this.invoiceHeaderService.updateById(scmInvoiceHeaderEntity);
            if (flg) {
                logger.debug("创建发票成功!凭证号为:" + invdocno);
            } else {
                logger.debug("创建发票失败!发票号为:" + scmInvoiceHeaderEntity.getInvoiceNo());
            }
            return invdocno;
        }
        String mes = (String) returnTable.getValue("MESSAGE");
        this.logger.debug(mes);
        return mes;
    }

    /**
     * @Description 发票Sap修改接口
     * @Param [invoiceEntity]
     * @Return java.lang.String
     * @Author socik
     * @Date 2019/5/21 11:20
     * <p>
     * TODO: ScmInvoiceEntity对象已经废弃，改为使用ScmInvoiceHeaderEntity
     */
    public String changeInvoiceToSap(ScmInvoiceEntity invoiceEntity) {
        logger.debug("发票修改接口!");
        JCoDestination destination = null;
        JCoFunction function = null;
        JCoParameterList tables = null;
        JCoParameterList importList = null;
        JCoParameterList returnList = null;
        try {
            destination = JCoDestinationManager.getDestination("IDOC_AFS");
            function = destination.getRepository().getFunction("ZFM_SRM_INCOMINGINVOICE_CHANGE ");
            tables = function.getTableParameterList();
            importList = function.getImportParameterList();
            returnList = function.getExportParameterList();
        } catch (JCoException e) {
            e.printStackTrace();
        }
        return "修改成功!";
    }

    /**
     * 计算税额
     *
     * @param billMonoey  对账单金额
     * @param taxCodeText 税代码文字 (J0-0% 进项税，中国)
     */
    @RequestMapping("/calTaxMoney")
    @ResponseBody
    public R calTaxMoney(BigDecimal billMonoey, String taxCodeText) {
        BigDecimal taxMoney = this.scmBillsService.calTaxMoney(billMonoey, taxCodeText);
        return R.ok(taxMoney);

    }

    /**
     * 计算付款日期
     *
     * @param kpDateStr       开票日期
     * @param payCondtionText 付款条件文字
     *                        情况格式1： H000-预付款(立刻到期)
     *                        情况格式2： H001-立刻到期(货到付款)
     *                        情况格式3： H005-月结120天
     *                        情况格式4： H008-次月10号
     */
    @RequestMapping("/calPayDate")
    @ResponseBody
    public R calPayDate(String kpDateStr, String payCondtionText) {
        String tmpStr = null;
        try {
            tmpStr = payCondtionText.substring(payCondtionText.indexOf("-") + "-".length());
        } catch (Throwable ex) {
            return R.error("付款条件表述不正确");
        }
        boolean containNum = tmpStr.matches("^.+\\d.+$");
        if (!containNum) {// 如果不包含数字，就是情况1和情况2，立即付款
            return R.ok(kpDateStr);
        }
        SunnykidDate kpD = null;
        try {
            kpD = SunnykidDate.parseSunnykidDate(kpDateStr);
        } catch (LangException ex) {
            return R.error("开票日期不正确");
        }
        if (tmpStr.indexOf("次月") >= 0x0) {// 情况4
            int year = kpD.year();
            int month = kpD.month();
            int day = getNumFromStr(tmpStr);
            if (month == 12) {
                month = 1;
                year++;
            } else {
                month++;
            }
            return R.ok(year + "-" + month + "-" + day);
        } else if (tmpStr.indexOf("月结") >= 0x0) {// 情况3
            int delayDays = getNumFromStr(tmpStr);// 延后付款的天数
            SunnykidDate fkDate = kpD.getNearByDays(delayDays);
            return R.ok(fkDate.getStandardDate());
        } else {
            return R.error("无法计算付款日期");
        }
    }

    /**
     * 从一堆字符串、符号、数字混合的字符串中提取出数字
     *
     * @param content
     * @return
     */
    private static int getNumFromStr(String content) {
        String regEx = "[^0-9]+";
        Pattern pattern = Pattern.compile(regEx);
        String[] cs = pattern.split(content);
        return Integer.parseInt(ArrayUtils.toString(cs, UtilCharacter.EMPTY));
    }

    /**
     * 查询列表
     */
    @RequestMapping("/list")
    @ResponseBody
    public R list(@RequestParam Map<String, Object> params) {
        SysUserEntity username = this.getUser();
        if (username.getDeptId() == 13) {
            params.put("username", username.getUsername());
        }
        PageUtils pu = this.invoiceHeaderService.selectDetailPage(params);
        List<ScmInvoiceHeaderEntity> voList = (List<ScmInvoiceHeaderEntity>) pu.getList();
        voList = EntityUtils.valToTxt(voList);
        return R.ok(pu);
    }
}
